#!/usr/bin/env python

from sys import *
from xml.etree import ElementTree as et

################################################################################

TERR = {
    'Plains': 'P', 'Hills':'H', 'Swamp':'S', 'Woods':'W', 'Desert':'D','Marsh':'M','Jungle':'J', 'Brush':'B',
    'Mountains':"m", 'Tundra':'t', "Tower":"T",
    }
PRETTY_EXIT = {
    'ARROWS': '>',
    'BLOCK' : ']',
    'ARCH'  : ')',
    'ARROW' : '}',
}

class Hex:
    def __init__(self, elem):
        self.label = elem.attrib['label']
        self.terrain = elem.attrib['terrain']
        self.exits = []
    def addExit(self, aexit):
        self.exits.append( aexit)
    def getTerrainId(self):
        return TERR[self.terrain]
    def __str__(self):
        return "%s%s" % (self.getTerrainId(), self.label)
    def __repr__(self):
        return "<%s%s>" % (self.getTerrainId(), self.label)

class Exit:
    def __init__(self, elem):
        self.type = elem.attrib['type']   # ARROWS, BLOCK, ARCH, ARROW
        self.label = elem.attrib['label']
    def __repr__(self):
        return "%s%s" % (PRETTY_EXIT[self.type], self.label)

################################################################################

def read_board(fn):
    doc = et.parse(fn)
    hexes = {}
    _cnt_exits = 0
    for hex_elem in doc.getiterator('hex'):
        hex = Hex(hex_elem)
        hexes[hex.label] = hex
        for exit_elem in hex_elem.getiterator('exit'):
            exi = Exit(exit_elem)
            hex.addExit(exi)
            _cnt_exits += 1
    print "### found %d hexes and %d exits" % ( len(hexes), _cnt_exits)
    return hexes

def _walk1(hexes, on_label, dice, follow, prev_label):
    if dice == 0:
        return on_label
    on_hex = hexes[on_label]
    to_labels = []
    for aexit in on_hex.exits:
        _type = aexit.type
        if _type not in follow:
            continue
        if _type == "BLOCK":
            return _walk1(hexes, aexit.label, dice-1, follow=["ARROWS"], prev_label=on_label)
        elif _type == "ARCH":
            to_labels.append( _walk1(hexes, aexit.label, dice-1, follow=["ARROWS","ARROW"], prev_label=on_label) )
        elif _type == "ARROW":
            if aexit.label == prev_label:
                continue
            to_labels.append( _walk1(hexes, aexit.label, dice-1, follow=["ARROWS","ARROW"], prev_label=on_label) )
        elif  _type == "ARROWS":
            to_labels.append( _walk1(hexes, aexit.label, dice-1, follow=["ARROWS"], prev_label=on_label) )
        else:
            raise "unknow type: %s" % _type
    return to_labels

def flatten(ls):
    if type(ls) != type([]):
        return [ls]
    res = []
    for l in ls:
        if type(l) == type([]):
            res.extend( flatten(l) )
        else:
            res.append(l)
    return set(res) # uniq

def walk(hexes, on_label, dice):
    end_labels = _walk1(hexes, on_label, dice, follow=["ARROWS", "BLOCK", "ARCH", "ARROW"], prev_label=None)
    end_labels = flatten(end_labels)
    return [ hexes[end_label] for end_label in end_labels ]


def prDice(terr):
    for t in "PMHWDSBJmtT":
        print "".join(map(str, terr[t])), "||",

def header():
    print "||||<rowbgcolor=cyan>From||1||2||3||4||5||6|| P||M||H||W||D||S||B||J||m||t||T||"

def main(fn):
    hexes = read_board(fn)
    nums = sorted(map(int, hexes.keys()))
    i = 0
    for n in nums:
        if i%20==0: header()
        _from = str(n)
        hex = hexes[_from]
        print "|||| %6s ||" % hex,
        terr = dict([ (t,[]) for t in TERR.values()])
        for dice in [1,2,3,4,5,6]:
            for _to in walk(hexes, _from, dice):
                terr[ TERR[_to.terrain] ].append(dice)
                print _to,
            print "||",
        prDice(terr)
        print
        i+=1
    header()

if __name__ == "__main__":
    main(argv[1])




